<template>
  <div ref="tableCardBoxRef" class="table-card-box">
    <!-- :stripe="!cardData.isNotStripe" -->
    <el-table
      v-if="refesh"
      ref="myTable"
      v-loading="loading"
      class="my-table"
      :data="tableData.body"
      :default-sort="defaultSort"
      :max-height="maxHeight"
      :row-style="setTdRowStyle"
      :cell-style="setTdStyle"
      :cell-class-name="setTdClass"
      :header-cell-style="setThStyle"
      :header-row-style="setThRowStyle"
      :reserve-selection="true"
      row-key="id"
      :default-expand-all="defaultExpandAll"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
      :header-cell-class-name="setThCellClassName"
      style="width: 100%"
      border
      :tooltip-effect="cardData.effect || 'light'"
      @expand-change="clickExpandChange"
      @sort-change="clickSortChange"
      @selection-change="clickSelectionChange"
      @cell-click="clickCell"
    >
      <template slot="empty">
        <div class="no-data-box" />
      </template>
      <el-table-column
        v-if="isMultiple"
        :fixed="'left'"
        type="selection"
        width="50"
      />
      <el-table-column
        v-if="isShowIndex"
        type="index"
        label="序号"
        width="60"
      />
      <template v-for="item in tableData.head">
        <el-table-column
          v-if="!item.operateList"
          :key="item.prop"
          :show-overflow-tooltip="true"
          :prop="item.prop"
          :label="item.name"
          :width="item.width"
          :min-width="item.minWidth"
          :fixed="item.fixed || false"
          :sortable="item.sortable"
          :align="item.align || ''"
        >
          <!-- 表格头部 -->
          <template slot="header">
            <span v-html="item.name" />
          </template>
          <!-- 二级 -->
          <el-table-column
            v-for="subItem in item.splitList"
            :key="subItem.prop"
            :show-overflow-tooltip="!cardData.isHideTooltip"
            :prop="subItem.prop"
            :label="subItem.name"
            :width="subItem.width"
            :min-width="subItem.minWidth"
            :fixed="subItem.fixed || false"
            :sortable="subItem.sortable"
          >
            <!-- 二级表格内容 -->
            <template slot-scope="scope">
              <span
                v-if="!subItem.componentCell"
                v-html="handlerCellData(scope.row, subItem)"
              />
              <component
                :is="subItem.componentCell"
                v-else
                :scope-data="scope"
                :refesh-cell="refeshCell"
                :table-data="tableData"
                :table-item="subItem"
                @clickBtn="clickBtn"
              />
            </template>
          </el-table-column>
          <!-- 表格内容 -->
          <template slot-scope="scope">
            <span
              v-if="!item.componentCell"
              v-html="handlerCellData(scope.row, item)"
            />
            <component
              :is="item.componentCell"
              v-else
              :scope-data="scope"
              :refesh-cell="refeshCell"
              :table-data="tableData"
              :table-item="item"
              @clickBtn="clickBtn"
            />
          </template>
        </el-table-column>
        <!-- 操作类 -->
        <el-table-column
          v-else
          :key="item.name"
          header-align="left"
          align="left"
          :label="item.name"
          :width="item.width"
          :min-width="item.minWidth"
          :fixed="false"
          style="text-align: left"
        >
          <template slot-scope="scope">
            <div class="operate-box">
              <template
                v-for="btnItem in handleBtnList(
                  item.operateList,
                  '',
                  scope.row
                )"
              >
                <component
                  :is="btnItem.btnType || 'el-button'"
                  :key="btnItem.id"
                  class="operate-item"
                  v-bind="btnItem.config"
                  :disabled="isDisabledBtn(btnItem, scope.row)"
                  :style="btnItem.style || {}"
                  @click="clickBtn(btnItem, scope.row)"
                >
                  <span class="vertical-line">|</span>
                  <span class="label">{{ btnItem.label }}</span>
                </component>
              </template>
              <div
                v-if="
                  handleBtnList(item.operateList, 'more', scope.row).length > 0
                "
                class="more-operate-box"
              >
                <span class="vertical-line">|</span>
                <el-dropdown placement="bottom-start">
                  <span class="el-dropdown-link">
                    <i class="el-icon-more" />
                  </span>
                  <el-dropdown-menu slot="dropdown">
                    <template
                      v-for="btnItem in handleBtnList(
                        item.operateList,
                        'more',
                        scope.row
                      )"
                    >
                      <el-dropdown-item
                        :key="btnItem.id"
                        class="custom-disabled-dropdown-item"
                        :disabled="isDisabledBtn(btnItem, scope.row)"
                        :style="btnItem.style || {}"
                      >
                        <div
                          v-if="!btnItem.hidden || !btnItem.hidden(scope.row)"
                          class="dropdown-item-text"
                          @click="clickBtn(btnItem, scope.row)"
                        >
                          {{ btnItem.label }}
                        </div>
                      </el-dropdown-item>
                    </template>
                  </el-dropdown-menu>
                </el-dropdown>
              </div>
            </div>
          </template>
        </el-table-column>
      </template>
    </el-table>

    <el-pagination
      v-if="!cardData.hidePagination"
      ref="paginationRef"
      background
      :current-page="currentPage"
      :page-sizes="cardData.pageSizes || [10, 30, 50, 100, 200, 500]"
      :page-size="pageSize"
      :layout="cardData.layout || 'total, sizes, prev, pager, next, jumper'"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import CellComponentItems from './CellComponent'
import { mapGetters } from 'vuex'
// import { deepClone } from '@/utils'

export default {
  name: 'TableCard',
  components: {
    ...(CellComponentItems || {})
  },
  props: {
    cardData: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      refesh: true,
      loading: false,
      defaultExpandAll: false,
      maxHeight: null,
      tableData: {
        head: [],
        body: []
      },
      currentPage: 1,
      pageSize: 10,
      total: 0,
      defaultSort: {},
      refeshCell: false
    }
  },
  computed: {
    ...mapGetters(['authList']),
    isMultiple() {
      return !!this.cardData.isMultiple
    },
    isShowIndex() {
      return !!this.cardData.isShowIndex
    },
    handleBtnList() {
      return (list, type, row) => {
        let filterList =
          list.filter((e) => {
            if (e.authId) {
              return this.authList.find((f) => f.permission === e.authId)
            }
            return true
          }) || []
        filterList = filterList.filter((e) => {
          return !e.hidden || !e.hidden(row)
        })
        const defaultList =
          filterList.filter((e, i) => (filterList.length > 3 ? i < 2 : true)) ||
          []
        const moreList =
          filterList.filter((e, i) =>
            filterList.length > 3 ? i > 1 : false
          ) || []
        if (type === 'more') {
          return moreList
        }
        return defaultList
      }
    },
    isDisabledBtn() {
      return (btnItem, row) => {
        const { disabledRules } = btnItem || {}
        if (disabledRules) {
          const { type = 'find', ruleList = [] } = disabledRules
          if (type === 'find') {
            return !!ruleList.find((e) => row[e.prop] === e.value)
          } else {
            return !!ruleList.every((e) => row[e.prop] === e.value)
          }
        }
        return false
      }
    }
  },
  watch: {
    cardData: {
      handler(data) {
        if (data) {
          const {
            head = [],
            body = [],
            total = 0,
            page = 1,
            limit = 10,
            sortOrder,
            sortColumn,
            defaultExpandAll
          } = data
          this.defaultExpandAll = defaultExpandAll || false
          this.tableData = { head, body }
          this.total = total
          this.currentPage = page
          this.pageSize = limit
          this.defaultSort =
            sortColumn && sortOrder
              ? { order: `${sortOrder}ending`, prop: sortColumn }
              : {}
          this.refeshCell = !this.refeshCell
        } else {
          this.tableData = { head: [], body: [] }
        }
        if (this.defaultExpandAll || data?.isRefeshTable) {
          this.refesh = false
          this.$nextTick((e) => {
            this.refesh = true
          })
        }
        console.log('-=-=-=高度重新计算')
        this.computeMaxHeight()
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    /**
     * @returns {*} 计算最大高度
     */
    computeMaxHeight() {
      this.$nextTick(() => {
        this.maxHeight = null // 设备列表不同条件查询后 maxHeight会导致数据样式问题
        const { tableCardBoxRef, paginationRef } = this.$refs || {}
        if (tableCardBoxRef) {
          this.maxHeight = paginationRef
            ? tableCardBoxRef.offsetHeight - paginationRef.$el.offsetHeight
            : tableCardBoxRef.offsetHeight
        }
      })
    },
    /**
     * 单元格数据处理
     * @param {*} row 行
     * @param {*} item 数据
     * @returns {*} 单元格数据
     */
    handlerCellData(row, item) {
      const { prop, format, resetConfig, mergeProp, formatter, mergeIcon } = item || {}
      let val = row[prop]
      if (formatter && typeof formatter === 'function') {
        return formatter(row, item)
      }
      if (resetConfig) {
        val = resetConfig[row[prop]] || row[prop]
      }
      if ([null, undefined, ''].includes(val)) {
        return '-'
      }
      if (mergeProp) {
        if (mergeIcon) {
          val = `${row[prop]} ${mergeIcon} ${row[mergeProp] || ''}`
        } else {
          val = `${row[prop]}（${row[mergeProp] || ''}）`
        }
      }
      if (format) {
        const { type, showType = '{y}-{m}' } = format
        if (type && type === 'date') {
          val = this.$formatDate(val, showType)
        } else {
          val = this.$formatData({ value: val, ...format })
        }
      }
      return val
    },
    /**
     * @returns {*} 表头tr样式
     */
    setThRowStyle({ row, column, rowIndex, columnIndex }) {
      let style = {
        'font-size': '14px',
        'font-weight': 600
      }
      const { head = [] } = this.tableData || {}
      const { thTrStyle = {}} =
        head.find((e) => e.thTrStyle && e.prop === column.property) || {}
      style = Object.assign(style, thTrStyle)
      return style
    },
    /**
     * @returns {*} 表头th样式
     */
    setThStyle({ row, column, rowIndex, columnIndex }) {
      let style = {
        'background-color': 'var(--table-th-bgColor)',
        'font-size': '14px',
        'font-weight': 600,
        color: 'var(--table-th-color)',
        height: '40px',
        'padding-left': '5px',
        'padding-right': '5px'
      }
      const { head = [] } = this.tableData || {}
      const { thStyle = {}} =
        head.find((e) => e.thStyle && e.prop === column.property) || {}
      style = Object.assign(style, thStyle)
      return style
    },
    /**
     * @returns {*} 表头th类名
     */
    setThCellClassName({ row, column, rowIndex, columnIndex }) {
      const { head = [] } = this.tableData || {}
      const { thClass = '' } =
        head.find((e) => e.thClass && e.prop === column.property) || {}
      return thClass
    },
    /**
     * @returns {*} 表体tr样式
     */
    setTdRowStyle({ row, column, rowIndex, columnIndex }) {
      let style = {}

      const { head = [] } = this.tableData || {}
      const { tdTrStyle = {}} =
        head.find((e) => e.tdTrStyle && e.prop === column.property) || {}
      style = Object.assign(style, tdTrStyle)

      return style
    },
    /**
     * @returns {*} 表体td样式
     */
    setTdStyle({ row, column, rowIndex, columnIndex }) {
      let style = {
        'text-align': 'left',
        'font-size': '14px',
        'font-weight': 400,
        color: 'var(--table-td-color)',
        height: '40px',
        padding: '0 5px'
      }
      const { head = [] } = this.tableData || {}
      const {
        tdStyle = {},
        dataTdStyle = {},
        filterTdStyle = {}
      } = head.find(
        (e) => (e.tdStyle || e.dataTdStyle) && e.prop === column.property
      ) || {}
      let isFilter = false
      if (filterTdStyle.filterType === 'empty' && filterTdStyle.filterProp) {
        isFilter = !row[filterTdStyle.filterProp]
      }
      if (!isFilter) {
        style = Object.assign(style, tdStyle)
      }
      if (dataTdStyle.dataProp) {
        style = Object.assign(style, dataTdStyle[row[dataTdStyle.dataProp]])
      }
      return style
    },
    /**
     * @returns {*} 表体td类名
     */
    setTdClass({ row, column, rowIndex, columnIndex }) {
      const { head = [] } = this.tableData || {}
      const { tdClass = '' } =
        head.find((e) => e.tdClass && e.prop === column.property) || {}
      return tdClass
    },
    /**
     * 点击展开
     * @param {*} data 数据
     * @returns {*} 无
     */
    clickExpandChange(data) {
      this.$emit('expandChange', data)
    },
    /**
     * 点击排序
     * @param {*} data 数据
     * @returns {*} 无
     */
    clickSortChange(data) {
      // data: {
      //   order: 排序 'descending' | 'ascending',
      //   prop: 排序字段
      // }
      // sortOrder: 排序 desc（降序） | asc （升序）
      // sortColumn: 排序字段
      const { order, prop } = data || {}
      const sortObj = {
        sortOrder: order ? order.replace('ending', '') : '',
        sortColumn: prop
      }

      this.$emit('sortParams', sortObj)
    },
    /**
     * 点击分页容量
     * @param {*} limit 页容量
     * @returns {*} 无
     */
    handleSizeChange(limit) {
      this.currentPage = 1
      this.pageSize = limit
      this.$emit('handleSizeChange', {
        limit: this.pageSize,
        page: this.currentPage
      })
    },
    /**
     * 点击分页页码
     * @param {*} page 页码
     * @returns {*} 无
     */
    handleCurrentChange(page) {
      this.currentPage = page
      this.$emit('handleCurrentChange', {
        limit: this.pageSize,
        page: this.currentPage
      })
    },
    /**
     * 点击selec行
     * @param {*} arr 数据
     * @returns {*} 无
     */
    clickSelectionChange(arr) {
      this.$emit('selectionChange', arr)
    },
    /**
     * 点击单元格
     * @returns {*} 无
     */
    clickCell(row, column) {
      const { clickConfig } =
        this.tableData.head.find((e) => e.prop === column.property) || {}
      if (clickConfig) {
        const {
          type,
          urlProp,
          routerName,
          routerPath,
          authId,
          paramsList = []
        } = clickConfig
        // clickConfig: {
        //   type: 'router-skip',
        //   routerName: 'UserManage',
        //   routerPath: '/systemManage/userManage',
        //   paramsList: ['id']
        // }
        if (type === 'router-skip') {
          const params = {}
          paramsList.forEach((key) => {
            params[key] = row[key]
          })
          if (authId) {
            const auth = this.authList.find((f) => f.permission === authId)
            if (!auth) {
              return
            }
          }
          if (routerName) {
            this.$router.push({
              name: routerName,
              params
            })
          } else if (routerPath) {
            this.$router.push({
              path: routerPath,
              query: params
            })
          }
          return
        }
        if (type === 'url-skip' && row[urlProp]) {
          const href = row[urlProp]
          const a = document.createElement('a')
          a.style.display = 'none'
          a.href = href
          a.target = '_blank'
          document.body.appendChild(a)
          a.click()
          document.body.removeChild(a)
          return
        }
        this.$emit('clickBtn', clickConfig, row)
      }
    },
    /**
     * 点击操作按钮
     * @returns {*} 无
     */
    clickBtn(item, row) {
      this.$emit('clickBtn', item, row)
    },
    // 回显选中状态
    toggleRowSelection(ids) {
      this.loading = true
      this.$nextTick(() => {
        const body = JSON.parse(JSON.stringify(this.tableData.body)) || []
        const selectionList =
          body.filter((e) => {
            return ids.includes(e.id)
          }) || []
        this.clearSelection()
        if (selectionList.length) {
          body.forEach((e, i) => {
            if (ids.includes(e.id)) {
              this.$refs.myTable.toggleRowSelection(
                this.tableData.body[i],
                true
              )
            }
          })
        }
        this.loading = false
      })
    },
    clearSelection() {
      this.$refs.myTable.clearSelection()
    }
  }
}
</script>

<style lang="scss" scoped>
.table-card-box {
  width: 100%;
  height: 100%;
}

::v-deep .el-table {
  background-color: var(--table-bgColor);

  .el-table__expand-icon {
    // float: right;
    .el-icon-arrow-right::before {
      content: '';
    }
  }

  .el-table-column--selection .cell {
    display: flex;
    justify-content: center;
  }

  &.el-table--border {
    border: 1px solid var(--table-borderColor);
    border-top: none;

    th {
      border-right: 1px solid transparent;
      border-bottom: 1px solid transparent;
    }

    td {
      border-right: 1px solid transparent;
      border-bottom: 1px solid var(--table-td-borderColor);
    }

    &::after {
      display: none;
    }
  }

  th.gutter {
    background-color: var(--table-th-bgColor);
  }

  &.el-table--striped .el-table__body tr.el-table__row--striped td {
    background-color: var(--table-tr-hover-bgColor);
  }

  .operate-box {
    display: flex;

    .vertical-line {
      color: #eee;
      margin-right: 10px;
    }

    .operate-item {
      font-size: 12px;
      &.el-button--text:hover .label {
        text-decoration: underline;
      }

      &:first-child .vertical-line {
        display: none;
      }
    }

    .more-operate-box {
      margin-left: 10px;
      display: flex;
      align-items: center;
      cursor: pointer;

      &:hover .el-icon-more {
        color: rgb(219,139,57);
      }

      .custom-disabled-dropdown-item {
        font-size: 12px;
      }
    }
  }
}

.el-pagination {
  display: flex;
  justify-content: flex-end;
  padding: 20px 0 0 0;
}
.is-disabled {
  color: #c0c4cc !important;
}
</style>
